<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Minio测试MD5秒传</title>
    <script src="js/vue.js"></script>
    <script src="js/jquery.js"></script>
    <script src="js/spark-md5.min.js"></script>
</head>
<body>
<div id="app">
    <form @submit.prevent="uploadFile">
        <label>
            文件
            <input type="file" @change="fileChange">
        </label>
        <br><br>
        <button type="submit" v-show="file != null">上传文件</button>
    </form>
    <p v-if="uploadStatus">{{ uploadStatus }}</p>
</div>

<script>
    var vm = new Vue({
        el: "#app",
        data() {
            return {
                file: null,
                fileMd5: null,
                uploadStatus: ""
            };
        },
        methods: {
            /**
             * 选择文件
             */
            fileChange(event) {
                this.file = event.target.files[0];
                if (this.file) {
                    this.uploadStatus = "正在计算文件MD5...";
                    this.calculateFileMd5();
                } else {
                    this.uploadStatus = "";
                }
            },
            /**
             * 计算文件的MD5值
             */
            async calculateFileMd5() {
                try {
                    const reader = new FileReader();
                    const spark = new SparkMD5.ArrayBuffer();

                    return new Promise((resolve, reject) => {
                        reader.onload = (e) => {
                            spark.append(e.target.result);
                            this.fileMd5 = spark.end();
                            console.log('File MD5:', this.fileMd5);
                            this.uploadStatus = "MD5: " + this.fileMd5;
                            resolve(this.fileMd5);
                        };

                        reader.onerror = () => {
                            reject(new Error("无法读取文件"));
                        };

                        reader.readAsArrayBuffer(this.file);
                    });
                } catch (error) {
                    console.error('计算MD5失败:', error);
                    this.uploadStatus = "计算MD5失败，请重试";
                    alert("计算MD5失败，请重试");
                    throw error;
                }
            },
            /**
             * 检查文件是否已存在
             */
            checkFileExists(md5, fileName) {
                return new Promise((resolve, reject) => {
                    $.ajax({
                        type: "POST",
                        url: "http://localhost:9989/oss/check",
                        contentType: 'application/json',
                        data: JSON.stringify({md5, fileName}),
                        success: (resp) => resolve(resp),
                        error: (xhr, status, error) => reject(new Error("检查文件是否存在时出错"))
                    });
                });
            },
            /**
             * 获取预签名URL
             */
            getPresignedUrl(fileName) {
                return new Promise((resolve, reject) => {
                    $.get('http://localhost:9989/oss/presign/url', {
                        bucketName: "demo",
                        fileName: fileName
                    }, resolve)
                        .fail(() => reject(new Error("无法获取预签名URL")));
                });
            },
            /**
             * 上传单个文件
             */
            putObject(url, file) {
                return new Promise((resolve, reject) => {
                    $.ajax({
                        url: url,
                        type: "PUT",
                        data: file,
                        processData: false,
                        contentType: false,
                        success: (response) => resolve(response),
                        error: (xhr, status, error) => reject(new Error(`上传失败: HTTP状态码 ${xhr.status}`))
                    });
                });
            },
            /**
             * 上传文件
             */
            async uploadFile() {
                if (!this.file) {
                    alert('请选择一个文件');
                    return;
                }

                try {
                    await this.calculateFileMd5();

                    this.uploadStatus = "正在检查文件是否存在...";
                    const exists = await this.checkFileExists(this.fileMd5, this.file.name);

                    if (exists) {
                        this.uploadStatus = "文件已存在，无需上传";
                        alert("文件已存在，无需上传");
                        return;
                    }

                    this.uploadStatus = "正在获取预签名URL...";
                    const url = await this.getPresignedUrl(`${this.fileMd5}_${this.file.name}`);

                    this.uploadStatus = "正在上传文件...";
                    await this.putObject(url, this.file);

                    this.uploadStatus = "上传成功";
                    alert("上传成功");
                } catch (error) {
                    console.error('上传失败:', error);
                    this.uploadStatus = "上传失败，请重试";
                    alert(`上传失败: ${error.message}`);
                }
            }
        }
    });
</script>
</body>
</html>